package com.jinhao.crowd.mvc.config;

import com.jinhao.crowd.util.CrowdConstant;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.access.AccessDeniedException;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.method.configuration.EnableGlobalMethodSecurity;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.web.access.AccessDeniedHandler;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;

/**
 * Created on 2021/10/3.
 *
 * @author Valar Morghulis
 */

// 标记为配置类
@Configuration
// 启用web环境下权限控制功能
@EnableWebSecurity
// 启用全局方法权限控制功能
@EnableGlobalMethodSecurity(prePostEnabled = true)
public class CrowdfundingSecurityConfig extends WebSecurityConfigurerAdapter {

    @Autowired
    private CrowdUserDetailsService userDetailsService;

    @Autowired
    private BCryptPasswordEncoder passwordEncoder;

    @Override
    protected void configure(AuthenticationManagerBuilder builder) throws Exception {

        /*builder
                .inMemoryAuthentication()                    // 内存登录
                .withUser("xiaojinhao").password("xjh3210")  // 账号密码
                .roles("ADMIN");                             // 设置角色*/
        // 真实的基于数据库的登录
        builder
                .userDetailsService(userDetailsService)
                .passwordEncoder(passwordEncoder);           // 带盐值的加密，框架提供
    }

    @Override
    protected void configure(HttpSecurity security) throws Exception {

        security
                .authorizeRequests()                        // 对请求进行授权
                .antMatchers("/admin/to/login/page.html")   // 登录页面放行
                .permitAll()                                // 允许全部请求
                .antMatchers("/bootstrap/**")               // 静态资源放行
                .permitAll()
                .antMatchers("/crowd/**")
                .permitAll()
                .antMatchers("/css/**")
                .permitAll()
                .antMatchers("/fonts/**")
                .permitAll()
                .antMatchers("/img/**")
                .permitAll()
                .antMatchers("/jquery/**")
                .permitAll()
                .antMatchers("/layer-v3.1.1/**")
                .permitAll()
                .antMatchers("/script/**")
                .permitAll()
                .antMatchers("/ztree/**")
                .permitAll()
                .antMatchers("/admin/get/page.html")                 // 针对某个访问地址
                .hasRole("部长")                                     // 要求具备某个角色
                .anyRequest()                                        // 其他未设置的全部请求
                .authenticated()                                     // 需要认证
                .and()
                .exceptionHandling()                                 // 开启访问被拒绝处理
                .accessDeniedHandler(new AccessDeniedHandler() {
                    @Override
                    public void handle(HttpServletRequest request, HttpServletResponse response, AccessDeniedException e) throws IOException, ServletException {
                        request.setAttribute("exception", new Exception(CrowdConstant.MESSAGE_ACCESS_DENIED));
                        // 重定向到系统错误页面
                        request.getRequestDispatcher("/WEB-INF/system-error.jsp").forward(request, response);
                    }
                })
                .and()
                .csrf()                                              // 防跨站请求
                .disable()                                           // 关闭
                .formLogin()                                         // 开启表单登录验证
                .loginPage("/admin/to/login/page.html")              // 指定登录页
                .loginProcessingUrl("/security/do/login.html")       // 登录提交表单的地址
                .usernameParameter("loginAcct")                      // 定制登录账号的请求参数名
                .passwordParameter("userPswd")
                .defaultSuccessUrl("/admin/to/main/page.html")       // 登录成功后默认前往的地址
                .and()
                .logout()                                            // 开启退出登录功能
                .logoutUrl("/security/do/logout.html")               // 自定义注销功能的URL地址
                .logoutSuccessUrl("/admin/to/login/page.html");      // 退出登录后跳转的地址
    }
}
